#	GÉNÉRATEUR ALÉATOIRE DE NOMBRES WICHMANN-HILL
#
#	B. A. Wichmann et I. D. Hill (1982)
#	Dans la revue Applied Statistics, numéro 31 (1982), pages 188-190 :
#	"Algorithm AS 183"
#	"An efficient and portable pseudo-random number generator"
#	("Un générateur de nombres pseudo-aléatoire efficace et portable")
#
#	voir aussi : 
#		Correction to Algorithm AS 183
#		Applied Statistics numéro 33 (1984), p123  
#
#		A. I. McLeod (1985)
#		A remark on Algorithm AS 183 
#		Applied Statistics numéro 34 (1985), p198-200
#
#
#	USAGE :
#	whrandom.random()	génère un nombre aléatoire à double précision 
#               distribué uniformément entre 0 et 1.
#
#	whrandom.seed()		doit être appelée avant whrandom.random()
#				pour créer la graine (seed) du générateur


#	Ce code est une transcription d'un code source C fourni par
#	Adrian Baddeley; Guido van Rossum s'est chargé de cette transcription.


# La graine
#
_seed = [0, 0, 0]


# Définit la graine
#
def seed(x, y, z):
	_seed[:] = [x, y, z]


# Renvoie le nombre aléatoire suivant de l'intervalle [0.0-1.0[
#
def random():
	from math import floor		# la fonction floor()
	#
	[x, y, z] = _seed
	x = 171 * (x % 177) - 2 * (x/177)
	y = 172 * (y % 176) - 35 * (y/176)
	z = 170 * (z % 178) - 63 * (z/178)
	#
	if x < 0: x = x + 30269
	if y < 0: y = y + 30307
	if z < 0: z = z + 30323
	#
	_seed[:] = [x, y, z]
	#
	term = float(x)/30269.0 + float(y)/30307.0 + float(z)/30323.0
	rand = term - floor(term)
	#
	if rand >= 1.0: rand = 0.0	# une imprécision de floor()?
	#
	return rand


# Initialise la graine à partir de l'heure actuelle
#
def init():
	import time
	t = time.time()
	seed(t%256, t/256%256, t/65536%256)


# On s'assure ici que le générateur a une valeur prédéfinie non-nulle
#
init()
